import { Component, Input, OnInit, ViewChild, OnChanges, SimpleChanges, ElementRef, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators, ValidationErrors } from "@angular/forms";
import { NzMessageService } from "ng-zorro-antd";
import { Observable, Observer } from 'rxjs';
import { FcsService } from "../../../../../service/fcs.service";
import { CommonService } from "../../../../../service/common.service";
import { debounceTime, distinctUntilChanged, first, map, switchMap } from 'rxjs/operators';
import { Subscriber, of } from 'rxjs';
import {randomBytes} from 'crypto';

@Component({
  selector: 'app-alias-create',
  encapsulation: ViewEncapsulation.None,
  templateUrl: './alias-create.component.html',
  styleUrls: ['./alias-create.component.less']
})

export class AliasCreateComponent implements OnInit {
  @ViewChild('AliasFormComponent', { static: true }) AliasFormComponent;
  aliasForm: FormGroup;
  @ViewChild('inputWeight1Element', { static: false }) inputWeight1Element?: ElementRef;
  @ViewChild('inputWeight2Element', { static: false }) inputWeight2Element?: ElementRef;  //version1Ele
  @ViewChild('version1Ele', { static: false }) version1Ele?: ElementRef;
  @ViewChild('version2Ele', { static: false }) version2Ele?: ElementRef;
  @Input() versionList = [];
  @Input() groupId: string = "";
  @Input() funcId: string = "";
  @Input() operation: string = ""; //config
  aliasRouter: string = 'weight';
  versions = [];
  lastWeight1: string = '0';
  weight1: string = '0';
  lastWeight2: string = '100';
  weight2: string = '100';
  version1: string = null;
  version2: string = null;
  weightPattern = /^0|[1-9][0-9]*$/; ///^(0|[1-9][0-9]*)(\.[0-9]*)?$/
  weightZeroPattern = /^0|[1-9][0-9]*$/;
  isDuplication: boolean = false;
  isAliasLoading: boolean = false;
  aliasId: string;
  aliasList = [];
  validAlias: boolean = false;
  constructor(
    private fb: FormBuilder,
    private fcsService: FcsService,
    private msgService: NzMessageService,
    private commonService: CommonService
  ) {
  }

  ngOnChanges(changes: SimpleChanges): void {

  }

  addVersions(versionList) {
    if (versionList && versionList.length > 0) {
      versionList.forEach(item => {
        // if(item.VersionName != "LATEST"){
        this.versions.push({
          label: item.VersionName,
          value: item.VersionId
        });
        // }
      })
    }
  }

  ngOnInit() {
    // 添加时间戳和随机数字段
    this.aliasForm.addControl('timestamp', new FormControl(Date.now()));
    this.aliasForm.addControl('nonce', new FormControl(randomBytes(5).toString(36).substring(0, 9)));

    this.setFormGroup();
    this.addVersions(this.versionList);
    this.getAlias();
  }

  setFormGroup() {
    let groupParams = {
      //aliasName: ['', [Validators.required]],
      description: ['', [Validators.maxLength(500), this.descriptionValid]],
      routerMethod: ['weight', [Validators.required]],
      version1: [null, [Validators.required]],
      version2: [null, [Validators.required]],
      weight1: ["0", [Validators.required]],
      weight2: ["100", [Validators.required]]
    };
    if (this.operation === 'creation') {
      groupParams['aliasName'] = ['', [Validators.required, this.alisNameValidator],[this.nameDuplicateValidator]];
    } else if (this.operation === 'config') {
      groupParams['alias'] = [null, [Validators.required]];
    }
    this.aliasForm = this.fb.group(groupParams);
  }

  getAlias() {
    if (this.operation === 'config') {
      this.isAliasLoading = true;
      this.fcsService.getAliasList(this.groupId, this.funcId).subscribe(res => {
        if (res && res['data']) {
          this.aliasList = res['data'];
        }
        this.isAliasLoading = false;
      }, err => {
        this.isAliasLoading = false;
      })
    }
  }

  getInvalidMessage(name) {
    return this.AliasFormComponent.getInvalidMessage(name);
  }

  alisNameValidator(control: FormControl): any {
    let name: string = control.value;
    //^(([a-z0-9]{2}[a-z0-9-]*)?[a-z0-9])?$
    let pattern = new RegExp('^[0-9a-z][0-9a-z-]*[0-9a-z]$');
    if (!pattern.test(name)) {
      return { aliasName: true };
    }
    return null;
  }

  descriptionValid(control: FormControl): any {
    let des: string = control.value || '';
    // 最大支持500个英文字母、数字、空格、逗号、句号、中文
    let pattern = new RegExp('^[a-zA-Z0-9 ,，。.\u4e00-\u9fa5]{0,500}$');
    if (!des) return null;
    if (!pattern.test(des)) {
      return { description: true };
    }
    return null;
  }

  aliasIdChange(value: string) {
    if (value != undefined && value != '') {
      this.validAlias = false;
      let willConfigAlias = this.aliasList.filter(item => item.aliasId === this.aliasId)[0];
      if (willConfigAlias) {
        this.aliasForm.get('description').patchValue((willConfigAlias['description'] || ''));
        this.aliasForm.get('routerMethod').patchValue(willConfigAlias['rule']['type']);
        if (willConfigAlias['rule']['type'] === 'weight') {
          if (willConfigAlias['rule']['traffic'][0]) {
            let version1Name = willConfigAlias['rule']['traffic'][0]['versionName'];
            let version1Id = this.versionList.filter(item => item.VersionName === version1Name)[0]['VersionId'];
            this.version1 = version1Id;
            this.weight1 = willConfigAlias['rule']['traffic'][0]['versionWeight'] + "";
          }
          if (willConfigAlias['rule']['traffic'][1]) {
            let version2Name = willConfigAlias['rule']['traffic'][1]['versionName'];
            let version2Id = this.versionList.filter(item => item.VersionName === version2Name)[0]['VersionId'];
            this.version2 = version2Id;
            this.weight2 = willConfigAlias['rule']['traffic'][1]['versionWeight'] + "";
          }
        }
      }
    }
  }

  aliasRouterChange() {

  }

  version1Change(value: string) {
    if (this.aliasForm.get("version1").dirty && !value) {
      this.aliasForm.get("version1").reset();
      this.aliasForm.get("weight1").reset();
      this.aliasForm.get("weight1").setValue("0");
    }
    this.version1 = value;
    this.determineDuplication();
  }

  version2Change(value: string) {
    if (this.aliasForm.get("version2").dirty && !value) {
      this.aliasForm.get("version2").reset();
      this.aliasForm.get("weight2").reset();
      this.aliasForm.get("weight2").setValue("0");
    }
    this.version2 = value;
    this.determineDuplication();
  }

  determineDuplication() {
    if (this.aliasForm.get("version1").dirty && !this.aliasForm.get("version1").value) {
      this.aliasForm.get("version1").reset();
      this.aliasForm.get("weight1").reset();
      this.aliasForm.get("weight1").setValue("0");
    }
    if (this.aliasForm.get("version2").dirty && !this.aliasForm.get("version2").value) {
      this.aliasForm.get("version2").reset();
      this.aliasForm.get("weight2").reset();
      this.aliasForm.get("weight2").setValue("0");
    }

    if (this.version1 && this.version2) {
      if (this.version1 === this.version2) {
        this.isDuplication = true;
      } else {
        this.isDuplication = false;
      }
    } else {
      this.isDuplication = false;
    }
  }

  weight1Change(value: string): void {
    if ((!isNaN(+value) && this.weightPattern.test(value)) && parseInt(value) <= 100) {
      this.weight1 = parseInt(value) + "";
      this.lastWeight1 = parseInt(value) + "";
      this.weight2 = 100 - parseInt(this.weight1) + "";
      if (this.inputWeight1Element != undefined && this.inputWeight2Element != undefined) {
        this.inputWeight1Element!.nativeElement.value = parseInt(value) + "";
        this.inputWeight2Element!.nativeElement.value = this.weight2;
      }
    } else {
      if (value != undefined) {
        if (value.trim() === '') {
          this.inputWeight1Element!.nativeElement.value = "0";
          this.inputWeight2Element!.nativeElement.value = "100";
        } else {
          this.weight1 = "100";
          this.inputWeight1Element!.nativeElement.value = this.lastWeight1;
          this.inputWeight2Element!.nativeElement.value = 100 - parseInt(this.lastWeight1) + "";
        }
      }
    }
  }

  weight2Change(value: string): void {
    if ((!isNaN(+value) && this.weightPattern.test(value)) && parseInt(value) <= 100) {
      this.weight2 = parseInt(value) + "";
      this.lastWeight2 = parseInt(value) + "";
      this.weight1 = 100 - parseInt(this.weight2) + "";
      if (this.inputWeight1Element != undefined && this.inputWeight2Element != undefined) {
        this.inputWeight2Element!.nativeElement.value = parseInt(value) + "";
        this.inputWeight1Element!.nativeElement.value = this.weight1;
      }
    } else {
      if (value != undefined) {
        if (value.trim() === '') {
          this.inputWeight2Element!.nativeElement.value = "0";
          this.inputWeight1Element!.nativeElement.value = "100";
        } else {
          this.weight2 = "100";
          this.inputWeight2Element!.nativeElement.value = this.lastWeight2;
          this.inputWeight1Element!.nativeElement.value = 100 - parseInt(this.lastWeight2) + "";
        }
      }
    }
  }


  // nameDuplicateValidator () {
  //   return (control: FormControl): any => {
  //     return control.valueChanges.pipe(
  //       distinctUntilChanged(),
  //       debounceTime(400),
  //       switchMap(() => this.isUserNameExist(control.value)),
  //       map(res => res['exist'] === true ? { duplicated: true } : null),
  //       first()
  //     );
  //   };
  // }
  
  nameDuplicateValidator = (control: FormControl) => {
    // 进入管道进行串行操作
    // valueChanges表示字段值变更才触发操作
    if (control && control.valueChanges) {
      return control.valueChanges.pipe(
        // 同valueChanges，不写也可
        distinctUntilChanged(),
        // 防抖时间，单位毫秒
        debounceTime(400),
        // 调用服务，参数可写可不写，如果写的话变成如下形式
        switchMap(() => this.isUserNameExist(control.value)),
        // 对返回值进行处理，null表示正确，对象表示错误
        map(res => { 
          return res.exist ? {error: true, duplicated: true} : null;
        }),
        // 每次验证的结果是唯一的，截断流
        first()
      );
    } else {
      return of(null);
    }

  }


  isUserNameExist(name: string): Observable<any> {
    if (name) {
      if (this && this.groupId && this.funcId) {
        return this.fcsService.functionAlias(this.groupId, this.funcId, name);
      }
    }
    return new Observable((observer: Subscriber<any>) => {
      setTimeout(() => {
        observer.next({ exist: false });
      }, 2000);
    });
  }

  preSubmit(){
    // 允许只设置一个版本
    if (this.aliasForm.get("version1").value || this.aliasForm.get("version2").value) {
      this.aliasForm.get("version1").clearValidators();
      this.aliasForm.get("version2").clearValidators();
      this.aliasForm.get("weight1").clearValidators();
      this.aliasForm.get("weight2").clearValidators();
      if (this.aliasForm.get("version1").value && !this.aliasForm.get("version2").value) {
        this.aliasForm.get("weight1").setValue("100")
      }
      if (this.aliasForm.get("version2").value && !this.aliasForm.get("version1").value) {
        this.aliasForm.get("weight2").setValue("100")
      }
    } else {
      this.aliasForm.get("version1").setValidators([Validators.required]);
      this.aliasForm.get("version2").setValidators([Validators.required]);
      this.aliasForm.get("weight1").setValidators([Validators.required]);
      this.aliasForm.get("weight2").setValidators([Validators.required]);
    }

    let skip1 = '', skip2 = '', skip3 = 'weight1', skip4 = 'weight2', skip5 = '', skip6 = '';
    if (this.operation === 'creation') {
      if (this.aliasRouter == 'rule') {
        skip1 = 'version1';
        skip2 = 'version2';
        skip3 = 'weight1';
        skip4 = 'weight2';
      }
      skip6 = 'alias';
    } else if (this.operation === 'config') {
      if (!this.aliasId) {
        skip1 = 'version1';
        skip2 = 'version2';
        skip3 = 'weight1';
        skip4 = 'weight2';
        skip5 = 'routerMethod'
      }
      skip6 = 'aliasName';
    }

    let group = this.aliasForm as FormGroup;
    for (const i in group.controls) {
      if (i) {
        if (i == skip1 || i == skip2 || i == skip3 || i == skip4 || i == skip5 || i == skip6) {
          group.controls[i].clearValidators();
          group.controls[i].updateValueAndValidity();
        } else {
          group.controls[i].markAsDirty();
          group.controls[i].updateValueAndValidity();
        }
      }
    }
    if (group.controls['alias'] && !group.controls['alias'].valid) {
      this.validAlias = true;
    } else {
      this.validAlias = false;
    }
  }

  submit(): Promise<any> {
    this.preSubmit();
    let group = this.aliasForm;
    return new Promise((resolve, reject) => {
      const interval = setInterval(() => {
        if (!group.pending) {
          clearInterval(interval);
          if (!group.valid) {
            resolve(false);
          } else {
            if (!group.valid) {
              this.msgService.error("请检查表单");
              resolve(false);
              
            } else {
              let params: { [index: string]: any } = {};
              params['groupId'] = this.groupId;
              params['funcId'] = this.funcId;
              let aliasName: string;  //配置使用
              if (this.operation === 'creation') {
                params['aliasName'] = this.aliasForm.get('aliasName').value;
              } else if (this.operation === 'config') {
                let aliasId = this.aliasForm.get('alias').value || '';
                aliasName = this.aliasList.filter(item => item.aliasId === aliasId)[0]['aliasName'];
                params['aliasName'] = aliasName;
              }
              params['description'] = this.aliasForm.get('description').value || '';
              let ruleParam = {
                type: this.aliasRouter,
                traffic: []
              }
              if (this.version1) {
                ruleParam.traffic.push({
                  versionName: this.versions.filter(item => item.value === this.version1)[0].label,
                  versionWeight: parseInt(this.weight1)
                });
              }
              if (this.version2) {
                ruleParam.traffic.push({
                  versionName: this.versions.filter(item => item.value === this.version2)[0].label,
                  versionWeight: parseInt(this.weight2)
                });
              }
              params['rule'] = ruleParam;
              if (this.operation === 'creation') {
                this.fcsService.createAlias(this.groupId, this.funcId, params).subscribe(res => {
                  if (res && res['aliasName']) {
                    this.msgService.success(res['message'] || '别名创建成功！');
                    resolve(true);
                  } else {
                    this.msgService.error('别名创建失败！');
                    reject();
                  }
                }, error => {
                  // this.msgService.error('创建别名失败！');
                  reject();
                })
              } else if (this.operation === 'config') {
                this.fcsService.updateFunctionAlias(this.groupId, this.funcId, aliasName, params).subscribe(res => {
                  if (res && res['aliasName']) {
                    this.msgService.success(res['message'] || '别名修改成功！');
                    resolve(true);
                  } else {
                    this.msgService.error('别名修改失败！');
                    reject();
                  }
                }, err => {
                  // this.msgService.error('修改别名失败！');
                  reject();
                })
              }
            }
          }
        }
      }, 500);
    });
  }

}
